package com.idudiao.sc.common.log.util;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.http.HttpUtil;
import com.dhcc.aml.common.core.constant.CommonConstants;
import com.dhcc.aml.common.core.constant.ModulesEnum;
import com.dhcc.aml.common.core.dto.log.MQLogDTO;
import com.dhcc.aml.common.core.dto.log.OperationLogDTO;
import com.dhcc.aml.common.core.entity.UserInfo;
import com.dhcc.aml.common.core.util.SpringContextHolder;
import com.dhcc.aml.common.core.util.WebUtils;
import com.idudiao.sc.common.log.event.OperationLogEvent;
import com.idudiao.sc.common.log.event.MQLogEvent;
import org.springframework.util.Assert;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Objects;

/**
 * 日志工具类
 * @author songyinyin
 * @date 2019/1/9 13:51
 */
public class LogUtils {

    /**
     * 获取 OperationLogDTO
     * @return dto
     */
    public static OperationLogDTO getOperationLog() {
        HttpServletRequest request = ((ServletRequestAttributes) Objects
                .requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        OperationLogDTO dto = new OperationLogDTO();
        UserInfo userInfo = WebUtils.getUserInfo();
        dto.setCreateTime(LocalDateTime.now());
        if (ObjectUtil.isNotNull(userInfo)) {
            dto.setCreateUser(userInfo.getUsername());
            dto.setCreateOrg(userInfo.getOrgId());
        }
        dto.setParams(URLUtil.decode(HttpUtil.toParams(request.getParameterMap())));
        return dto;
    }

    /**
     * 保存用户操作日志
     * @param module 模块
     * @param operation 操作
     * @param targetKey 业务主键
     * @param notes 备注
     */
    public static void saveOperationLogRemote(ModulesEnum module, String operation, String targetKey, String notes) {
        Assert.hasLength(targetKey, "业务主键不能为空");
        OperationLogDTO dto = getOperationLog();
        dto.setModule(module.name());
        dto.setOperation(operation);
        dto.setTargetKey(targetKey);
        dto.setNotes(notes);
        SpringContextHolder.publishEvent(new OperationLogEvent(dto));
    }

    /**
     * 保存用户操作日志
     * @param module 模块
     * @param operation 操作
     * @param targetKey 业务主键
     * @param notes 备注
     * @param result 返回结果
     * @param time 用时
     */
    public static void saveOperationLogRemote(ModulesEnum module, String operation, String targetKey,
                                     String notes, String result, Long time) {
        Assert.hasLength(targetKey, "业务主键不能为空");
        OperationLogDTO dto = getOperationLog();
        dto.setModule(module.name());
        dto.setOperation(operation);
        dto.setTargetKey(targetKey);
        dto.setNotes(notes);
        dto.setResult(result);
        dto.setTime(time);
        SpringContextHolder.publishEvent(new OperationLogEvent(dto));
    }

    /**
     * 发送MQ时记录日志
     * @param batchNo 批次号，自己生产，必填
     * @param sendSummary 摘要，如："20190420发送了...机构xx待处理的数据"等
     * @param sendContent 内容
     */
    public static void saveMQLogRemote(String batchNo, String sendSummary, String sendContent) {
        Assert.hasLength(batchNo, "批次号不能为空");
        MQLogDTO dto = new MQLogDTO();
        dto.setBatchNo(batchNo);
        dto.setSendStatus(CommonConstants.MQ_STATUS_YES);
        dto.setSendTime(LocalDateTime.now());
        dto.setSendSummary(sendSummary);
        dto.setSendContent(sendContent);
        SpringContextHolder.publishEvent(new MQLogEvent(dto));
    }

    /**
     * 消费 成功 MQ消息时，更新日志
     * @param batchNo 批次号，从消息中获取，必填
     * @param receiveSummary 摘要，如："执行了...条数据，用时...毫秒"等
     */
    public static void updateMQLogSuccess(String batchNo, String receiveSummary) {
        Assert.hasLength(batchNo, "批次号不能为空");
        MQLogDTO dto = new MQLogDTO();
        dto.setBatchNo(batchNo);
        dto.setReceiveStatus(CommonConstants.MQ_STATUS_YES);
        dto.setReceiveTime(LocalDateTime.now());
        dto.setReceiveSummary(receiveSummary);
        SpringContextHolder.publishEvent(new MQLogEvent(dto));
    }

    /**
     * 消费 失败 MQ消息时，更新日志
     * @param batchNo 批次号，从消息中获取，必填
     * @param e 异常信息
     */
    public static void updateMQLogFail(String batchNo, Throwable e) {
        Assert.hasLength(batchNo, "批次号不能为空");
        MQLogDTO dto = new MQLogDTO();
        dto.setBatchNo(batchNo);
        dto.setReceiveStatus(CommonConstants.MQ_STATUS_NO);
        dto.setReceiveTime(LocalDateTime.now());
        dto.setReceiveSummary(ExceptionUtil.getMessage(e));
        dto.setReceiveException(ExceptionUtil.stacktraceToString(e, 20000));
        SpringContextHolder.publishEvent(new MQLogEvent(dto));
    }
}
